package com.ruoyi.platform.service.impl;

import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.platform.domain.*;
import com.ruoyi.platform.domain.request.InspectionLedgerRequest;
import com.ruoyi.platform.domain.vo.InspectionLedgerVo;
import com.ruoyi.platform.exception.BusinessException;
import com.ruoyi.platform.mapper.*;
import com.ruoyi.platform.service.IAsyncService;
import com.ruoyi.platform.service.IMWarningPushService;
import com.ruoyi.platform.service.IMWarningService;
import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysOperLogService;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @program: RuoYi-Vue
 * @description: 异步执行实现类
 * @author: drgon
 * @create: 2025-9-20 58：58
 */
@Service
@Async("asyncServiceExecutor")
public class AsyncServiceImpl implements IAsyncService {
    private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
    @Autowired
    private MExecuteCommandMapper mExecuteCommandMapper;

    @Autowired
    private MMonitoringEquipmentMapper monitoringEquipmentMapper;

    @Autowired
    private MStoreLocationMapper storeLocationMapper;

    @Autowired
    private MExecuteCommandResultMapper executeCommandResultMapper;



    @Autowired
    private ISysOperLogService sysOperLogService;

    @Autowired
    private IMWarningService warningService;

    @Autowired
    private IMWarningPushService warningPushService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    private final String platformCommandType = "platform_command_type";

    @Override
    @Async("asyncServiceExecutor")
    public void executeAsyncExecuteCommand(Long commandResultId, Boolean isRetrySend, LoginUser loginUser) {
        logger.info("线和池异步调用-----执行指令开始");
        executeCommand(commandResultId, isRetrySend, loginUser);
        logger.info("线和池异步调用-----执行指令结束");
    }



    /**
     * 执行指令
     *
     * @param commandResultId 执行结果记录ID
     * @param isRetrySend
     */
    private void executeCommand(Long commandResultId, Boolean isRetrySend, LoginUser loginUser) {
        MExecuteCommandResult executeCommandResult = executeCommandResultMapper.selectMExecuteCommandResultByCommandResultId(commandResultId);
        if (executeCommandResult != null) {
            MExecuteCommand command = mExecuteCommandMapper.selectMExecuteCommandByCommandId(executeCommandResult.getCommandId());
            if (command != null) {
                MStoreLocation storeLocation = storeLocationMapper.selectMStoreLocationByStoreLocationId(command.getStoreLocationId());
                MMonitoringEquipment equipment = monitoringEquipmentMapper.selectMMonitoringEquipmentByEquipmentId(storeLocation.getEquipmentId());
                command.setExecuteCommandResult(executeCommandResult);
                command.setLocation(storeLocation);
                command.setEquipment(equipment);
                MExecuteCommandResult updateResult = new MExecuteCommandResult();
                updateResult.setCommandResultId(commandResultId);
                /**设指指令最新执行时间为检验指令时间**/
                updateResult.setExecuteStartTime(DateUtils.getNowDate());
                MExecuteCommand updateCommand = new MExecuteCommand();
                updateCommand.setCommandId(command.getCommandId());
                try {
                    checkSendCommand(command);
                } catch (BusinessException ex) {
                    /**考虑是否抛出异常到前端**/
                    updateResult.setExecutionStatus(0);
                    updateResult.setContent(String.format("指令发送验证失败：%s", ex.getMessage()));
                    executeCommandResultMapper.updateMExecuteCommandResult(updateResult);
                    updateCommand.setWarningStatus(0);
                    mExecuteCommandMapper.updateMExecuteCommand(updateCommand);
                    saveOperLog(loginUser
                            , buildTitle(command, isRetrySend)
                            , "后端用户调用执行指令"
                            , commandResultId.toString()
                            , 1
                            , String.format("指令发送验证失败：%s", ex.getMessage()));
                    return;
                }

                /**更新指令最新执行时间为调用海康SDK时间**/
                updateResult.setExecuteStartTime(DateUtils.getNowDate());
                try {
                    Integer warningType = null;
                    if (!isRetrySend) {
                        /**组装发送指令内容**/
                        if (command.getCommandType().equals(0) || command.getCommandType().equals(1)) {
                            warningType = 0;
                            command.setContent(command.getCommandType().equals(0) ? "出货指令牌" : "入货指令");
                        } else if (command.getCommandType().equals(2)) {
                            /**
                             * 巡检
                             */
                            warningType = 1;
                            command.setContent("巡检");
                            updateCommand.setInspectionOperator(loginUser != null ? loginUser.getUsername() : "JOB");
                        } else if (command.getCommandType().equals(3)) {
                            /**
                             * 自动巡检
                             */
                            warningType = 2;
                            command.setContent("自动巡检");
                            updateCommand.setInspectionOperator(loginUser != null ? loginUser.getUsername() : "JOB");
                        }
                    }
                    /**TODO
                     * 调用海康SDK执行命令,待完成。
                     *
                     *
                     *
                     *
                     * **/
                    /**随机模拟返回接果成功*/
                    Boolean isSuccess = RandomUtils.nextBoolean();
                    Boolean isWarning = RandomUtils.nextBoolean();
                    /**更新执行指令记录**/
                    updateCommand.setCommandContent("指令测试");
                    updateCommand.setWarningStatus(2);
                    updateCommand.setCommandExecutionStatus(2);
                    updateCommand.setInspectionStatus(command.getCommandType());
                    updateCommand.setInspectionQuantity(RandomUtils.nextInt(10, 100));
                    updateCommand.setInspectionOperator(loginUser != null ? loginUser.getUsername() : "JOB定时任务");
                    updateCommand.setCommandExecuteTime(DateUtils.getNowDate());
                    /**更新执行指令记录结果**/
                    updateResult.setExecuteEndTime(DateUtils.getNowDate());
                    updateResult.setCommandResultId(commandResultId);
                    updateResult.setExecuteEndTime(DateUtils.getNowDate());
                    updateResult.setContent("指令测试");
                    if (isSuccess) {
                        /**更新仓位信息**/
                        updateResult.setExecutionStatus(2);
                        MStoreLocation location = new MStoreLocation();
                        location.setStoreLocationId(command.getLocation().getStoreLocationId());
                        location.setUpdateTime(DateUtils.getNowDate());
                        location.setStoreLocationStatus(command.getCommandType().longValue());
                        location.setQuantity(updateCommand.getInspectionQuantity().longValue());
                        storeLocationMapper.updateMStoreLocation(location);
                    } else {
                        updateResult.setExecutionStatus(1);
                        updateCommand.setCommandExecutionStatus(1);
                    }
                    executeCommandResultMapper.updateMExecuteCommandResult(updateResult);
                    mExecuteCommandMapper.updateMExecuteCommand(updateCommand);
                    /**
                     * 接收预警信息
                     */
                    if (isWarning && command.getLocation().getUseWarningPush().equals(1L)) {
                        MWarning warning = new MWarning();
                        warning.setEquipmentId(command.getEquipmentId());
                        warning.setStoreLocationCode(command.getLocation().getStoreLocationCode());
                        warning.setStoreLocationId(command.getLocation().getStoreLocationId());
                        warning.setCommandResultId(commandResultId);
                        warning.setCreateDate(DateUtils.getNowDate());
                        warning.setCreateDate(DateUtils.getNowDate());
                        warning.setWarningTime(DateUtils.getNowDate());
                        warning.setWarningType(warningType.longValue());
                        warning.setWarningContent("");
                        Integer warningId = warningService.insertMWarning(warning);
                        MWarningPush warningPush = new MWarningPush();
                        warningPush.setWarningId(warningId.longValue());
                        warningPush.setWarningPushContent("");
                        warningPush.setWarningPushTime(DateUtils.getNowDate());
                        warningPush.setWarningPushStatus(2L);
                        warningPush.setCreateTime(DateUtils.getNowDate());
                        if (loginUser != null) {
                            warningPush.setCreateBy(loginUser.getUsername());
                        }
                        warningPushService.insertMWarningPush(warningPush);
                    }

                } catch (Exception ex) {
                    /**SDK调用异常时处理**/
                    saveOperLog(loginUser, buildTitle(command, isRetrySend)
                            , "后端用户调用执行指令"
                            , commandResultId.toString()
                            , 1
                            , String.format("系统异常：%s", ex.getMessage()));
                }
            }
        }
    }


    /**
     * 保存指令牌执行日志
     *
     * @param title
     * @param method
     * @param operParam
     * @param status
     * @param errorMsg
     */
    private void saveOperLog(LoginUser loginUser, String title, String method, String operParam, Integer status, String errorMsg) {
        SysOperLog operLog = new SysOperLog();
        operLog.setTitle(title);
        operLog.setMethod(method);
        operLog.setOperId(1L);
        operLog.setBusinessType(1);
        operLog.setRequestMethod("Put");
        operLog.setOperatorType(1);
        operLog.setStatus(status);
        operLog.setErrorMsg(errorMsg);
        operLog.setOperTime(DateUtils.getNowDate());
        if (loginUser != null) {
            operLog.setOperName(loginUser.getUsername());
            operLog.setOperId(loginUser.getUserId());
        } else {
            operLog.setOperName("JOB");
            operLog.setOperId(0L);
        }
        operLog.setOperParam(operParam);
        sysOperLogService.insertOperlog(operLog);

    }

    private String buildTitle(MExecuteCommand command, Boolean isRetrySend) {
        return String.format("仓位[%s-%s]-[%s]指令-%s"
                , command.getLocation().getStoreLocationName()
                , command.getLocation().getStoreLocationCode()
                , DictUtils.getDictLabel(platformCommandType, command.getCommandType().toString())
                , isRetrySend ? "执行" : "重试执行");
    }

    private void checkSendCommand(MExecuteCommand mExecuteCommand) throws BusinessException {
        if (mExecuteCommand.getEquipment() == null) {
            throw new BusinessException("设备ID不存在");
        }
        if (mExecuteCommand.getLocation() == null) {
            throw new BusinessException("仓位ID不存在");
        }

        if (mExecuteCommand.getLocation().getUseStatus().equals(0L)) {
            throw new BusinessException("仓位状态为未启用");
        }
        if (mExecuteCommand.getEquipment().getUseStatus().equals(0L)) {
            throw new BusinessException("设备状态为未启用");
        }

        if (mExecuteCommand.getExecuteCommandResult() == null) {
            throw new BusinessException("指令执行结果信息不存在");
        }
    }

}
